#include "myapp.h"
#include "repprt.h"
#include <wx/dcbuffer.h>

DECLARE_APP(MyApp);
int setfieldobj;
wxPoint bpos, drgpos, odrgpos;

//---------------------------------------------------------------------------------
//  local function
//---------------------------------------------------------------------------------
wxPoint GetCenterringDrawing(int direction, int base_x, int base_y, int object_w, int object_h, int off_x = 0, int off_y = 0)
{
	int sub_x = 0, sub_y = 0;
	wxPoint pos;
//210cm 18cm
	if ((direction == wxVERTICAL) || (direction == wxBOTH)) {
		sub_y = ((float)(base_y - object_h) / 2.0f) + off_y;
	}
	if ((direction == wxHORIZONTAL) || (direction == wxBOTH)) {
		sub_x = ((float)(base_x - object_w) / 2.0f) + off_x;
	}
	pos.x = sub_x;
	pos.y = sub_y;
	return pos;
}
wxPoint GetLeftingDrawing(int margin_t, int margin_l, int off_x = 0, int off_y = 0)
{
	wxPoint pos;
	pos.x = margin_l + off_x;
	pos.y = margin_t + off_y;
	return pos;
}
wxPoint GetRightingDrawing(int base_x, int base_y, int object_w, int object_h, int off_x = 0, int off_y = 0)
{
	int sub_x = 0;
	wxPoint pos;
	sub_x = (base_x - object_w) + off_x;
	pos.x = sub_x;
	pos.y = 0;
	return pos;
}
//---------------------------------------------------------------------------------
//  ReportCanvas
//---------------------------------------------------------------------------------
BEGIN_EVENT_TABLE(ReportCanvas, wxScrolledWindow)
	//EVT_PAINT(ReportCanvas::OnPaint)
	EVT_MOUSE_EVENTS(ReportCanvas::OnMouse)
	//EVT_SIZE(ReportCanvas::OnSized)
	//EVT_SCROLLWIN(ReportCanvas::OnScrolled)
END_EVENT_TABLE() 

ReportCanvas::ReportCanvas(wxWindow *parent, const wxPoint &pos, const wxSize &size)
:wxScrolledWindow(parent,wxID_ANY,pos,size,wxBORDER_STATIC)
{
	repmode = 0;
	wxSize maxsize = GetSize();
	SetVirtualSize(maxsize.GetWidth()*5,maxsize.GetHeight()*5);
	SetBackgroundStyle(wxBG_STYLE_CUSTOM);
	SetBackgroundColour(wxColour(128,128,128));
	zoomx = 1.0;
	zoomy = 1.0;
	bpos = wxPoint(-1,-1);
}
void ReportCanvas::SetReportMode(int type)
{
	repmode = type;
}
void ReportCanvas::Draw(wxDC *dc)
{
	//dc->Clear();
	//---draw paper
	dc->SetBackgroundMode(wxTRANSPARENT);
	dc->SetPen(wxPen(*wxWHITE,1,wxSOLID));
	dc->SetBrush(wxBrush(*wxWHITE,wxSOLID));
	dc->DrawRectangle(5,5,realsize.GetWidth(),realsize.GetHeight());

	//dc->SetPen(wxPen(*wxBLACK,1,wxSOLID));
	//dc->SetFont(this->GetFont());
	//dc->DrawText(_T("Hello World!"),15,15);
}
//void ReportCanvas::OnPaint(wxPaintEvent &event)
void ReportCanvas::OnDraw(wxDC &dc)
{
	//wxPaintDC dc(this);
	//wxAutoBufferedPaintDC dc( this );
	DoPrepareDC(dc);
	dc.SetBrush(wxBrush(wxColour(128,128,128)));
	dc.SetPen(wxPen(wxColour(128,128,128)));
	dc.SetBackground(wxBrush(wxColour(128,128,128)));
	dc.DrawRectangle(0,0,GetSize().GetWidth(),GetSize().GetHeight());

	//vector<FieldLabel>::iterator flit;
	//vector<FieldLine>::iterator flnit;
	if (!pageInfo.IsOk()) return;
	dc.SetUserScale(zoomx,zoomy);
	Draw(&dc);
	//dc.SetBrush(wxBrush(wxColour(255,198,175),wxCROSS_HATCH));
	//dc.DrawRectangle(10,10,125,35);


	//---pre drawing object
	if ((bpos.x > -1) && (bpos.y > -1)) {
		dc.SetPen(wxPen(*wxWHITE,1,wxSOLID));
		dc.DrawLine(bpos.x,bpos.y,odrgpos.x,odrgpos.y);

		dc.SetPen(wxPen(*wxBLACK,1,wxDOT));
		dc.DrawLine(bpos.x,bpos.y,drgpos.x,drgpos.y);
	}
	//---drawing object
	dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
}
void ReportCanvas::SetPageInfo(const wxPageSetupDialogData &ps)
{
	pageInfo = ps;
	wxSize tmpsize = pageInfo.GetPaperSize();
	int rw;
	int rh;
	if (pageInfo.GetPrintData().GetOrientation() == wxPORTRAIT) {
		rw = tmpsize.GetWidth() * 3.2;
		rh = tmpsize.GetHeight() * 3.2;
	}else{
		rw = tmpsize.GetHeight() * 3.2;
		rh = tmpsize.GetWidth() * 3.2;
	}
	float wrate = 1.0;
	bool wflag = false, hflag = false;
	int pux = 0, puy = 0, nox = 0, noy = 0;
	realsize.SetWidth(rw);
	realsize.SetHeight(rh);
	SetVirtualSize(rw,rh);
	//calculate initial zoom rate
	SetZoom(1.0, 1.0);
}
void ReportCanvas::SetZoom(double x, double y)
{
	zoomx = x;
	zoomy = y;
	ZoomedFunction(realsize);
	Refresh();
}
void ReportCanvas::ZoomedFunction(const wxSize &size)
{
	bool wflag = false, hflag = false;
	int pux = 0, puy = 0, nox = 0, noy = 0;
	int rw = (int)((double)size.GetWidth() * zoomx);
	int rh = (int)((double)size.GetHeight() * zoomy);
	if (rw > GetSize().GetWidth()) {
		int difx = rw - 15;
		wflag = true;
		pux = 50;
		nox = difx / pux + 1;
	}
	if (rh > GetSize().GetHeight()) {
		int dify = rh - 15;
		wflag = true;
		puy = 50;
		noy = dify / puy + 1;
	}
	EnableScrolling(wflag,hflag);
	SetScrollbars(pux,puy,nox,noy);

}
void ReportCanvas::OnMouse(wxMouseEvent &event)
{
	wxClientDC dc(this);
	PrepareDC(dc);
	if (event.LeftDown()) {
		//--- get starting point
		switch (setfieldobj) {
		case repdlg_fline:
			bpos = event.GetLogicalPosition(dc);
			if (zoomx != 1.0) {
				bpos.x = (int)((double)bpos.x / zoomx);
				bpos.y = (int)((double)bpos.y / zoomy);
			}
			drgpos = bpos;
			break;
		}
	}
	if (event.LeftUp()) {
		/*switch (setfieldobj) {
		case repdlg_flabel: {
			wxString str = wxGetTextFromUser(_("Please input some text."));
			if (str.IsEmpty()) return;
			FieldLabel fl;
			fl.label = str;
			fl.position = event.GetLogicalPosition(dc);
			if (zoomx != 1.0) {
				fl.position.x = (int)((double)fl.position.x / zoomx);
				fl.position.y = (int)((double)fl.position.y / zoomy);
			}
			fLabels.push_back(fl);
			Refresh();
			}
			break;
		case repdlg_fline: {
			FieldLine fl;
			fl.start = bpos;
			fl.end = event.GetLogicalPosition(dc);
			if (zoomx != 1.0) {
				fl.end.x = (int)((double)fl.end.x / zoomx);
				fl.end.y = (int)((double)fl.end.y / zoomy);
			}
			fLines.push_back(fl);
			Refresh();
			bpos = wxPoint(-1,-1);
			drgpos = wxPoint(-1,-1);
			odrgpos = wxPoint(-1,-1);
			}
			break;
		}*/
	}
	if (event.Dragging() && (bpos.x > -1)) {
		drgpos = event.GetLogicalPosition(dc);
		if (zoomx != 1.0) {
			drgpos.x = (int)((double)drgpos.x / zoomx);
			drgpos.y = (int)((double)drgpos.y / zoomy);
		}
		odrgpos = drgpos;
		Refresh();
	}
}
void ReportCanvas::OnSized(wxSizeEvent &event)
{
	
}
void ReportCanvas::OnScrolled(wxScrollWinEvent &event)
{
	
}
//---------------------------------------------------------------------------------
//  ReportDialog
//---------------------------------------------------------------------------------
BEGIN_EVENT_TABLE(ReportDialog, wxDialog)
	EVT_BUTTON(repdlg_close,ReportDialog::ctrlClose_clicked)
	EVT_CHOICE(repdlg_zoom,ReportDialog::lctrlZoom_changed)
END_EVENT_TABLE() 

ReportDialog::ReportDialog(wxWindow *parent)
:wxDialog(parent,wxID_ANY,_("Design of report"),wxDefaultPosition, wxSize(750,570),wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER|wxMINIMIZE_BOX)
{
	repControl = new wxPanel(this,wxID_ANY,wxPoint(0,0),wxSize(-1,50));
	repCanvas = new ReportCanvas(this,wxPoint(0,0),wxSize(640,500));

	//---repControl
	wxString zoom_items[] = {
		_T("x0.5"),_T("x0.7"),_T("x1"),_T("x2")
	};

	ctrlOpen = new wxButton(repControl, wxID_ANY, _("Open"), wxPoint(-1,-1),wxSize(100,-1));
	ctrlSave = new wxButton(repControl, wxID_ANY, _("Save"), wxPoint(-1,-1),wxSize(100,-1));
	ctrlClose = new wxButton(repControl, repdlg_close, _("Close"), wxPoint(-1,-1),wxSize(100,-1));
	ctrlClear = new wxButton(repControl, wxID_ANY, _("Clear"), wxPoint(-1,-1),wxSize(100,-1));
	wxStaticText *label1 = new wxStaticText(repControl,wxID_ANY,_("Zoom size"));
	lctrlZoom = new wxChoice(repControl,repdlg_zoom,wxDefaultPosition,wxSize(65,-1),4,zoom_items);
	lctrlZoom->SetSelection(2);

	wxBoxSizer *rcsizer = new wxBoxSizer(wxHORIZONTAL);
	rcsizer->Add(ctrlOpen,0,wxTOP|wxLEFT,0);
	rcsizer->Add(ctrlSave,0,wxTOP|wxLEFT,0);
	rcsizer->Add(ctrlClose,0,wxTOP|wxLEFT,0);
	rcsizer->Add(ctrlClear,0,wxTOP|wxLEFT,0);
	rcsizer->AddSpacer(10);
	rcsizer->Add(label1,0,wxTOP,3);
	rcsizer->Add(lctrlZoom,0,wxTOP|wxLEFT,0);
	repControl->SetSizer(rcsizer);
	repControl->Layout();


	wxBoxSizer *bsizer1 = new wxBoxSizer(wxVERTICAL);
	bsizer1->Add(repControl,0,wxTOP|wxLEFT,5);
		wxBoxSizer *bsizer2 = new wxBoxSizer(wxHORIZONTAL);
		//bsizer2->Add(repLeftControl,0,wxEXPAND|wxLEFT,0);
		bsizer2->Add(repCanvas,1,wxEXPAND|wxTOP|wxLEFT,0);
	bsizer1->Add(bsizer2,1,wxEXPAND|wxLEFT,0);
	this->SetSizer(bsizer1);
	this->Layout();

}
void ReportDialog::ctrlClose_clicked(wxCommandEvent &event)
{
	this->EndModal(repdlg_close);
	this->Hide();
}
void ReportDialog::lctrlZoom_changed(wxCommandEvent &event)
{
	switch (event.GetSelection()) {
	case 0:
		repCanvas->SetZoom(0.5,0.5);
		break;
	case 1:
		repCanvas->SetZoom(0.7,0.7);
		break;
	case 2:
		repCanvas->SetZoom(1.0,1.0);
		break;
	case 3:
		repCanvas->SetZoom(2.0,2.0);
		break;
	}
}
void ReportDialog::Bind_PageData(wxPageSetupDialogData *ps)
{
	pageInfo = ps;
	repCanvas->SetPageInfo(*pageInfo);
}
void ReportDialog::Bind_Setup(DB_setting &setdb)
{
	repCanvas->SetFont(setdb.GetFontInfo());
}


//---------------------------------------------------------------------------------
//  ReportPrintout
//---------------------------------------------------------------------------------
ReportPrintout::ReportPrintout(wxWindow *parent, const wxString &title)
: wxPrintout(title)
{
	frame = parent;
	titlefont.SetPointSize(16);
	textfont.SetPointSize(12);
	report_type = 0;
	margin_tl.x = 0;
	margin_tl.y = 0;
	margin_br.x = 0;
	margin_br.y = 0;
	linespace = 5;
	data_perpage = 20;
	startdataindex = 0;
	oldpage = 1;
}
ReportPrintout &ReportPrintout::operator =(const ReportPrintout &pout)
{
	if (this == &pout) return *this;
	report_type = pout.report_type;
	dbdata.assign(pout.dbdata.begin(),pout.dbdata.end());
	dbtotal = pout.dbtotal;
	dbreserve = pout.dbreserve;
	reservediff = pout.reservediff;
	dbweekly = pout.dbweekly;
	title = pout.title;
	for (int i = 0; i < 3; i++) {
		header[i] = pout.header[i];
		footer[i] = pout.footer[i];
	}
	headerline = pout.headerline;
	footerline = pout.footerline;
	margin_tl = pout.margin_tl;
	margin_br = pout.margin_br;
	textfont = pout.textfont;
	data_perpage = pout.data_perpage;
	linespace = pout.linespace;
	options = pout.options;
	searchconditions = pout.searchconditions;
	return *this;
}
void ReportPrintout::Bind_DB_day(std::vector<DB_day>::iterator st, std::vector<DB_day>::iterator ed)
{
	dbdata.assign(st,ed);
}
void ReportPrintout::Bind_DB_reserved(DB_reserved &db, int diff)
{
	dbreserve = db;
	reservediff = diff;
}
void ReportPrintout::Bind_DB_weeklymonthly(DBL_WeeklyReport &db)
{
	dbweekly = db;
}
void ReportPrintout::SetHeaderString(wxArrayString &report_header)
{
	for (int i = 0; i < (int)report_header.GetCount(); i++) {
		if (i <= 2) {
			header[i] = report_header.Item(i);
		}else{
			break;
		}
	}
}
void ReportPrintout::SetFooterString(wxArrayString &report_footer)
{
	for (int i = 0; i < (int)report_footer.GetCount(); i++) {
		if (i <= 2) {
			footer[i] = report_footer.Item(i);
		}else{
			break;
		}
	}
}
void ReportPrintout::SetReportMargin(int topm, int leftm, int rightm, int bottomm)
{
	margin_tl.y = topm;
	margin_tl.x = leftm;
	margin_br.y = bottomm;
	margin_br.x = rightm;
}
wxString ReportPrintout::GetHeaderEscapeString(const wxString &str, int page)
{
	wxString rep;
	rep = str;
	rep.Replace(_T("%B"),wxGetApp().AppDB.AppSetting.GetBookName().c_str());
	rep.Replace(_T("%T"),this->title.c_str());
	rep.Replace(_T("%p"),IntToStr(page));
	rep.Replace(_T("%P"),IntToStr(GetTotalPageNumber()));
	rep.Replace(_T("%D"),wxDateTime::Today().FormatDate());
	return rep;
}
void ReportPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
{
    *minPage = 1;
    *maxPage = GetTotalPageNumber();
    *selPageFrom = 1;
    *selPageTo = GetTotalPageNumber();
}
bool ReportPrintout::HasPage(int page)
{
	return ((page >= 1) && (page <= GetTotalPageNumber()));
	//return ((page >= 1) && (page <= 2));
}
inline int ReportPrintout::GetTotalPageNumber(void)
{
	int totalpage;
	int amari;
	switch (report_type) {
	case 0:
		totalpage = (int)dbdata.size() / data_perpage;
		amari = (int)dbdata.size() % data_perpage;
		break;
	case 1:
	case 2:
		totalpage = (int)dbweekly.GetCount() / data_perpage;
		amari = (int)dbweekly.GetCount() % data_perpage;
		break;
	case 3:
		totalpage = (int)dbdata.size() / data_perpage;
		amari = (int)dbdata.size() % data_perpage;
		break;
	}
	totalpage = totalpage + (amari > 0 ? 1 : 0);
	return totalpage;
}
void ReportPrintout::SetOptions(wxArrayInt &opt)
{
	options = opt;
}
bool ReportPrintout::OnBeginDocument(int startPage, int endPage)
{
	if (!wxPrintout::OnBeginDocument(startPage, endPage)) {
		return false;
	}
	return true;
}
void ReportPrintout::OnPreparePrinting()
{
	//option: don't show expense, what's transaction is zero
	if (options.Item(2) == 1) {
		//Day or Search
		if ((report_type == 0) || (report_type == 3)) {
			for (size_t i = dbdata.size()-1; i > 0; i--) {
				if ((dbdata.at(i).GetIncome() == 0) && (dbdata.at(i).GetExpenditure() == 0)) {
					dbdata.erase(dbdata.begin()+i);
				}
			}
		}
		//Weekly or Monthly
		if ((report_type == 1) || (report_type == 2)) {
			for (size_t i = dbweekly.GetCount()-1; i > 0; i--) {
				if (dbweekly.Item(i).GetAmount(0) == 0) dbweekly.RemoveAt(i);
			}
		}
	}
	{//calculate data maximum size per page
		int ppiScreenX, ppiScreenY;
		GetPPIScreen(&ppiScreenX, &ppiScreenY);
		int ppiPrinterX, ppiPrinterY;
		GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
		float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);

		wxDC *dc = GetDC();
		int pageWidth, pageHeight;
		int w, h;
		int pageWidthMM, pageHeightMM;
		int tmpx, tmpy;
		dc->GetSize(&w, &h);
		GetPageSizePixels(&pageWidth, &pageHeight);
		GetPageSizeMM(&pageWidthMM, &pageHeightMM);
		dc->SetFont(textfont);
		dc->GetTextExtent(_T("TEST"),&tmpx,&tmpy);

		float overallScale = scale * (float)(w/(float)pageWidth);
		dc->SetUserScale(overallScale, overallScale);
		float logUnitsFactor = (float)(ppiPrinterX/(scale*25.4));
		float logUnits = (float)(50*logUnitsFactor);

		int realw = (int)(logUnitsFactor*(float)(pageWidthMM-margin_br.x));
		int realh = (int)(logUnitsFactor*(float)(pageHeightMM-margin_br.y));
		//------calculate page width and height CONTAINING margin
		pageWidthMM *= logUnitsFactor;
		pageHeightMM *= logUnitsFactor;
		
		data_perpage = ((realh-(margin_tl.y*logUnitsFactor)) / (tmpy+linespace)) - 4;
	}
}
bool ReportPrintout::OnPrintPage(int page)
{
	wxDC *dc = GetDC();
	if (dc) {

		DrawPage(dc,page);
		oldpage = page;
		return true;
	}else{
		return false;
	}
}
void ReportPrintout::DrawPage(wxDC *dc, int page)
{
	/*
	The item which I should be able to acquire to a minimum
	  *page width (in pixel)
	  *page height(in pixel)
	  *page margin (top, left, right, bottom) (in pixel)
	*/
	dc->SetPen(*wxBLACK_PEN);
	dc->SetBackground(*wxWHITE_BRUSH);

    int ppiScreenX, ppiScreenY;
    GetPPIScreen(&ppiScreenX, &ppiScreenY);
    int ppiPrinterX, ppiPrinterY;
    GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
    float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);

    int pageWidth, pageHeight;
    int w, h;
    int pageWidthMM, pageHeightMM;
    dc->GetSize(&w, &h);
    GetPageSizePixels(&pageWidth, &pageHeight);
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);

    float overallScale = scale * (float)(w/(float)pageWidth);
    dc->SetUserScale(overallScale, overallScale);
    float logUnitsFactor = (float)(ppiPrinterX/(scale*25.4));
    float logUnits = (float)(50*logUnitsFactor);

	//---set initial position and page size
	int x, y;
	int tmpx, tmpy;
	wxPoint textpos;
	//------calculate margin
	x = (int)(logUnitsFactor * (float)margin_tl.x);
	y = (int)(logUnitsFactor * (float)margin_tl.y);
	//------calculate page width and height MINUS margin
	int realw = (int)(logUnitsFactor*(float)(pageWidthMM-margin_br.x));
	int realh = (int)(logUnitsFactor*(float)(pageHeightMM-margin_br.y));
	//------calculate page width and height CONTAINING margin
	pageWidthMM *= logUnitsFactor;
	pageHeightMM *= logUnitsFactor;

	//---start drawing report
	if (options.Item(0) == 1) {
		dc->DrawRectangle(x,y, realw-x,realh-y);
	}
	//------report header
	textfont.SetPointSize(12);
	dc->SetFont(textfont);
	DrawHeader(dc,page,logUnitsFactor);
	//------report title
	/*dc->SetFont(titlefont);
	dc->SetTextForeground(*wxBLACK);
	dc->GetTextExtent(this->GetTitle(),&tmpx,&tmpy);
	textpos = GetCenterringDrawing(wxHORIZONTAL,pageWidthMM,pageHeightMM,tmpx,tmpy);
	dc->DrawText(this->GetTitle(),textpos.x,y);*/

	//---report contents
	switch (report_type) {
	case 0: //Day
		if (dbdata.size() > 0) DrawDayReport(dc,page,logUnitsFactor,realw,realh);
		break;
	case 1: //Week
	case 2: //Month
		if (dbweekly.GetCount() > 0) DrawWeeklyMonthlyReport(report_type,dc,page,logUnitsFactor,realw,realh);
		break;
	case 3: //Search
		if (dbdata.size() > 0) DrawSearchReport(dc,page,logUnitsFactor,realw,realh);
		break;
	}
	//------report footer
	textfont.SetPointSize(12);
	dc->SetFont(textfont);
	dc->SetTextForeground(*wxBLACK);
	DrawFooter(dc,page,logUnitsFactor);
}
void ReportPrintout::DrawHeader(wxDC *dc, int page, float mm_to_logi)
{
	int x, y;
    int pageWidthMM, pageHeightMM;
	int realw, realh;
	int tmpx, tmpy;
	wxPoint textpos;
	wxString hd[3];
	int fontpix;

	x = (int)(mm_to_logi * (float)margin_tl.x);
	y = (int)(mm_to_logi * (float)margin_tl.y);
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);
	pageWidthMM *= mm_to_logi;
	pageHeightMM *= mm_to_logi;
	realw = (pageWidthMM - x);
	realh = (pageHeightMM - y);
	
	fontpix = (int)((float)((float)textfont.GetPointSize() / (72.0f / 25.4f)) * mm_to_logi);
	y -= fontpix + linespace;

	if (!header[0].IsEmpty()) {
		hd[0] = this->GetHeaderEscapeString(header[0],page);
		dc->GetTextExtent(hd[0],&tmpx,&tmpy);
		textpos = GetLeftingDrawing(y,x);
		dc->DrawText(hd[0],textpos.x,y);
	}
	if (!header[1].IsEmpty()) {
		hd[1] = this->GetHeaderEscapeString(header[1],page);
		dc->GetTextExtent(hd[1],&tmpx,&tmpy);
		textpos = GetCenterringDrawing(wxHORIZONTAL,pageWidthMM,pageHeightMM,tmpx,tmpy);
		dc->DrawText(hd[1],textpos.x,y);
	}
	if (!header[2].IsEmpty()) {
		hd[2] = this->GetHeaderEscapeString(header[2],page);
		dc->GetTextExtent(hd[2],&tmpx,&tmpy);
		textpos = GetRightingDrawing(realw,realh,tmpx,tmpy);
		dc->DrawText(hd[2],textpos.x,y);
	}
	if (headerline) {
		dc->DrawLine(x,y+fontpix+5, realw,y+fontpix+5);
	}
}
void ReportPrintout::DrawFooter(wxDC *dc, int page, float mm_to_logi)
{
	int x, y;
    int pageWidthMM, pageHeightMM;
	int realw, realh;
	int tmpx, tmpy;
	wxPoint textpos;
	wxString ft[3];

	x = (int)(mm_to_logi * (float)margin_tl.x);
	y = (int)(mm_to_logi * (float)margin_tl.y);
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);
	pageWidthMM *= mm_to_logi;
	pageHeightMM *= mm_to_logi;
	realw = (pageWidthMM - x);
	realh = (pageHeightMM - y);

	y = realh;

	if (footerline) {
		dc->DrawLine(x,y, realw,y);
	}
	y += linespace;
	if (!footer[0].IsEmpty()) {
		ft[0] = this->GetHeaderEscapeString(footer[0],page);
		dc->GetTextExtent(ft[0],&tmpx,&tmpy);
		textpos = GetLeftingDrawing(y,x);
		dc->DrawText(ft[0],textpos.x,y);
	}
	if (!footer[1].IsEmpty()) {
		ft[1] = this->GetHeaderEscapeString(footer[1],page);
		dc->GetTextExtent(ft[1],&tmpx,&tmpy);
		textpos = GetCenterringDrawing(wxHORIZONTAL,pageWidthMM,pageHeightMM,tmpx,tmpy);
		dc->DrawText(ft[1],textpos.x,y);
	}
	if (!footer[2].IsEmpty()) {
		ft[2] = this->GetHeaderEscapeString(footer[2],page);
		dc->GetTextExtent(ft[2],&tmpx,&tmpy);
		textpos = GetRightingDrawing(realw,realh,tmpx,tmpy);
		dc->DrawText(ft[2],textpos.x,y);
	}
}
void ReportPrintout::DrawDayReport(wxDC *dc, int page, float mm_to_logi, int pw, int ph)
{
	int x, y;
    int pageWidthMM, pageHeightMM;
	int realw, realh;
	int tmpx, tmpy;
	wxPoint textpos;
	wxString colname[] = {
		_("Expense"),_("Items"),_("Memo"),_("Income"),_("Expenditure"),
	};
	int colwidth[] = {
		34,34,50,15,15
	};
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);
	pageWidthMM *= mm_to_logi;
	pageHeightMM *= mm_to_logi;
	//---set initial position and page size
	x = (int)(mm_to_logi * (float)margin_tl.x);
	y = (int)(mm_to_logi * (float)margin_tl.y);
	realw = (pw - x);// - (int)(mm_to_logi * (float)(margin_br.x));
	realh = (ph - y);// - (int)(mm_to_logi * (float)(margin_br.y));

	//y += 64;//tmpy;
	//dc->SetPen(*wxRED_PEN);
	//dc->DrawLine(x, y+15, realw, y+15);
	//---report contents
	dc->SetFont(textfont);
	dc->SetTextForeground(*wxBLACK);
	dc->SetPen(*wxBLACK_PEN);
	//------draw a date
	textfont.SetPointSize(14);
	dc->SetFont(textfont);
	dc->GetTextExtent(dbdata.at(0).GetDate().FormatDate(),&tmpx,&tmpy);
	textpos = GetLeftingDrawing(y,x,30);
	dc->DrawText(dbdata.at(0).GetDate().FormatDate(),textpos.x,y);
	y += tmpy;
	dc->DrawLine(textpos.x-5,y, textpos.x+tmpx+5,y);
	y += linespace;
	//------draw a handling
	{
		wxString accname;
		accname = wxGetApp().AppDB.GetAccount(dbdata.at(0).GetHandling()).GetName();
		textfont.SetPointSize(12);
		dc->SetFont(textfont);
		dc->GetTextExtent(accname,&tmpx,&tmpy);
		textpos.x = x + 95;
		y += linespace;
		dc->DrawText(accname,textpos.x,y);
		y += tmpy;
		dc->SetPen(*wxBLACK_PEN);
		dc->DrawLine(textpos.x-5,y, textpos.x+tmpx+5,y);
	}
	//------draw other data
	textfont.SetPointSize(10);
	dc->SetFont(textfont);
	{
		y += linespace + 10;
		//------draw column name
		textpos.x = x + 5;
		for (int i = 0; i < WXSIZEOF(colname); i++) {
			dc->GetTextExtent(colname[i],&tmpx,&tmpy);
			dc->DrawText(colname[i],textpos.x, y);
			textpos.x += colwidth[i]*mm_to_logi;
		}
		y += tmpy + linespace;
	}
	//------draw each data
	int cnt = 0;
	if (page < oldpage) {
		//------if return previous page, return index too.
		//startdataindex = startdataindex - (data_perpage * (page));
		startdataindex = data_perpage * (page - 1);
	}
	for (int i = startdataindex; i < (int)dbdata.size(); i++) {
		textpos.x = x + 5;
		dc->SetTextForeground(*wxBLACK);
		if (cnt >= data_perpage) {
			//startdataindex = i;
			break;
		}else{
			wxArrayString arr;
			arr = wxGetApp().AppDB.GetStringDayTransaction(dbdata.at(i));
			wxString memo = arr.Item(6);
			//---delete and sort
			arr.RemoveAt(6); //Memo
			arr.RemoveAt(3); //Account
			arr.RemoveAt(0); //Date
			arr.Insert(memo,2);
			for (int j = 0; j < (int)arr.GetCount(); j++) {
				dc->GetTextExtent(arr.Item(j),&tmpx,&tmpy);
				if (j <= 2) {
					dc->DrawText(arr.Item(j),textpos.x,y);
				}else{
					//------numeric columns 
					wxPoint vpos;
					if (j == 4) dc->SetTextForeground(*wxRED);
					vpos = GetRightingDrawing(colwidth[j]*mm_to_logi,y,tmpx,tmpy);
					dc->DrawText(arr.Item(j),textpos.x+vpos.x,y);
				}
				textpos.x += colwidth[j]*mm_to_logi;
			}

		}
		cnt++;
		y += tmpy + linespace;
	}
	dc->SetTextForeground(*wxBLACK);
	//------draw total of data
	if (page == GetTotalPageNumber()) {
		wxPoint vpos;
		const wxString CST_SUMTITLE = _("Total of income and expenditure");
		const wxString CST_REMAINDER = _("remainder");
		textpos.x = x + 5;
		y += 10;
		for (int i = 0; i < WXSIZEOF(colwidth)-3; i++) {
			textpos.x += colwidth[i]*mm_to_logi;
		}
		dc->GetTextExtent(CST_SUMTITLE,&tmpx,&tmpy);
		dc->DrawText(CST_SUMTITLE,textpos.x,y);
		textpos.x += colwidth[2]*mm_to_logi;
		//------total income
		dc->GetTextExtent(IntToStr(dbtotal.GetIncome()),&tmpx,&tmpy);
		vpos = GetRightingDrawing(colwidth[3]*mm_to_logi,y,tmpx,tmpy);
		dc->DrawText(IntToStr(dbtotal.GetIncome()),textpos.x+vpos.x,y);
		textpos.x += colwidth[3]*mm_to_logi;
		//------total expenditure
		dc->SetTextForeground(*wxRED);
		dc->GetTextExtent(IntToStr(dbtotal.GetExpenditure()),&tmpx,&tmpy);
		vpos = GetRightingDrawing(colwidth[4]*mm_to_logi,y,tmpx,tmpy);
		dc->DrawText(IntToStr(dbtotal.GetExpenditure()),textpos.x+vpos.x,y);
		textpos.x += colwidth[4]*mm_to_logi;

		//------total remainder
		textpos.x = x + 5;
		for (int i = 0; i < WXSIZEOF(colwidth)-3; i++) {
			textpos.x += colwidth[i]*mm_to_logi;
		}
		y += tmpy + linespace;
		dc->DrawLine(textpos.x-5,y+tmpy, textpos.x+((colwidth[2]+colwidth[3]+colwidth[4])*mm_to_logi)+5,y+tmpy);
		dc->SetTextForeground(*wxBLACK);
		dc->GetTextExtent(CST_REMAINDER,&tmpx,&tmpy);
		dc->DrawText(CST_REMAINDER,textpos.x,y);
		textpos.x += colwidth[2]*mm_to_logi;
		textpos.x += colwidth[3]*mm_to_logi;

		dc->GetTextExtent(IntToStr(dbtotal.GetRemainder()),&tmpx,&tmpy);
		vpos = GetRightingDrawing(colwidth[4]*mm_to_logi,y,tmpx,tmpy);
		dc->DrawText(IntToStr(dbtotal.GetRemainder()),textpos.x+vpos.x,y);
		y += tmpy;

		if (dbreserve.GetId() > -1) {
			dc->SetTextForeground(*wxBLACK);
			//------current budget
			textpos.x = x + 5;
			y += tmpy + linespace;
			for (int i = 0; i < WXSIZEOF(colwidth)-3; i++) {
				textpos.x += colwidth[i]*mm_to_logi;
			}
			wxString BUDTITLE = StrF(_("A Budget (%d/%d)"),
				dbreserve.GetStartDate().GetYear(),dbreserve.GetStartDate().GetMonth()+1);
			dc->GetTextExtent(BUDTITLE,&tmpx,&tmpy);
			dc->DrawText(BUDTITLE,textpos.x,y);
			textpos.x += colwidth[2]*mm_to_logi;
			textpos.x += colwidth[3]*mm_to_logi;

			dc->GetTextExtent(IntToStr(dbreserve.GetValue()),&tmpx,&tmpy);
			vpos = GetRightingDrawing(colwidth[4]*mm_to_logi,y,tmpx,tmpy);
			dc->DrawText(IntToStr(dbreserve.GetValue()),textpos.x+vpos.x,y);

			//------the difference of a budget and the income and expenditure
			textpos.x = x + 5;
			y += tmpy + linespace;
			for (int i = 0; i < WXSIZEOF(colwidth)-3; i++) {
				textpos.x += colwidth[i]*mm_to_logi;
			}
			dc->DrawLine(textpos.x-5,y+tmpy, textpos.x+((colwidth[2]+colwidth[3]+colwidth[4])*mm_to_logi)+5,y+tmpy);
			BUDTITLE = _("A Remainder of the budget");
			dc->GetTextExtent(BUDTITLE,&tmpx,&tmpy);
			dc->DrawText(BUDTITLE,textpos.x,y);
			textpos.x += colwidth[2]*mm_to_logi;
			textpos.x += colwidth[3]*mm_to_logi;

			if (reservediff < 0) dc->SetTextForeground(*wxRED);
			dc->SetTextForeground(*wxBLACK);
			dc->GetTextExtent(IntToStr(reservediff),&tmpx,&tmpy);
			vpos = GetRightingDrawing(colwidth[4]*mm_to_logi,y,tmpx,tmpy);
			dc->DrawText(IntToStr(reservediff),textpos.x+vpos.x,y);
		}
	}

}
void ReportPrintout::DrawWeeklyMonthlyReport(int type, wxDC *dc, int page, float mm_to_logi, int pw, int ph)
{
	int x, y;
    int pageWidthMM, pageHeightMM;
	int realw, realh;
	int tmpx, tmpy;
	wxPoint textpos;
	wxString colname[] = {
		_("Expense"),_("Items"),_("Income and expenditure")
	};
	int colwidth[] = {
		34,34,15
	};
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);
	pageWidthMM *= mm_to_logi;
	pageHeightMM *= mm_to_logi;
	//---set initial position and page size
	x = (int)(mm_to_logi * (float)margin_tl.x);
	y = (int)(mm_to_logi * (float)margin_tl.y);
	realw = (pw - x);
	realh = (ph - y);
	//y += 64;

	dc->SetFont(textfont);
	dc->SetTextForeground(*wxBLACK);
	dc->SetPen(*wxBLACK_PEN);

	//---draw date
	{
		wxString fmtDate;
		switch (type) {
		case 1: //Week
			fmtDate = dbtotal.GetDate().FormatDate();
			break;
		case 2: //Month
			fmtDate = dbtotal.GetDate().Format(_T("%Y/%m"));
			break;
		}
		textfont.SetPointSize(14);
		dc->SetFont(textfont);
		dc->GetTextExtent(fmtDate,&tmpx,&tmpy);
		textpos = GetLeftingDrawing(y,x,30);
		dc->DrawText(fmtDate,textpos.x,y);
		y += tmpy;
		dc->DrawLine(textpos.x-5,y, textpos.x+tmpx+5,y);
		y += linespace;
	}
	//---draw a handling
	{
		wxString accname;
		accname = wxGetApp().AppDB.GetAccount(dbtotal.GetHandling()).GetName();
		textfont.SetPointSize(12);
		dc->SetFont(textfont);
		dc->GetTextExtent(accname,&tmpx,&tmpy);
		textpos.x = x + 95;
		dc->DrawText(accname,textpos.x,y);
		y += tmpy;
		dc->SetPen(*wxBLACK_PEN);
		dc->DrawLine(textpos.x-5,y, textpos.x+tmpx+5,y);
	}
	y += linespace;
	//---draw column name
	textfont.SetPointSize(10);
	dc->SetFont(textfont);
	textpos.x = x + 5;
	for (int i = 0; i < WXSIZEOF(colname); i++) {
		dc->GetTextExtent(colname[i],&tmpx,&tmpy);
		dc->DrawText(colname[i],textpos.x, y);
		textpos.x += colwidth[i]*mm_to_logi;
	}
	y += tmpy + linespace;
	//------draw each data
	int cnt = 0;
	bool iochange_in = false, iochange_out = false;
	if (page != oldpage) {
		//------if return previous page, return index too.
		// 1 - 0~19, 2 - 20~39, 3 - 40~59 ...
		//startdataindex = startdataindex - (data_perpage * (page));
		startdataindex = data_perpage * (page - 1);
	}
	for (int i = startdataindex; i < (int)dbweekly.GetCount(); i++) {
		textpos.x = x + 5;
		dc->SetTextForeground(*wxBLACK);
		if (cnt >= data_perpage) {
			//startdataindex = i;
			break;
		}else{
			if (!iochange_in && (dbweekly.Item(i).GetIO(0) == in_it)) {
				iochange_in = true;
				wxString tmpname = StrF(_T("<<%s>>"),_("Income"));
				dc->GetTextExtent(tmpname,&tmpx,&tmpy);
				y += tmpy;
				dc->DrawText(tmpname,textpos.x,y);
				y += tmpy * 2 + linespace;
			}
			if (!iochange_out && (dbweekly.Item(i).GetIO(0) == out_it)) {
				iochange_out = true;
				wxString tmpname = StrF(_T("<<%s>>"),_("Expenditure"));
				dc->GetTextExtent(tmpname,&tmpx,&tmpy);
				y += tmpy;
				dc->DrawText(tmpname,textpos.x,y);
				y += tmpy * 2 + linespace;
			}
			
			dc->GetTextExtent(dbweekly.Item(i).GetExpenseName(),&tmpx,&tmpy);
			dc->DrawText(dbweekly.Item(i).GetExpenseName(),textpos.x,y);
			textpos.x += colwidth[0]*mm_to_logi;

			dc->GetTextExtent(dbweekly.Item(i).GetItemName(),&tmpx,&tmpy);
			dc->DrawText(dbweekly.Item(i).GetItemName(),textpos.x,y);
			textpos.x += colwidth[1]*mm_to_logi;

			{//------numeric columns
				wxPoint vpos;
				dc->GetTextExtent(IntToStr(dbweekly.Item(i).GetAmount(0)),&tmpx,&tmpy);
				vpos = GetRightingDrawing(colwidth[2]*mm_to_logi,y,tmpx,tmpy);
				if (dbweekly.Item(i).GetIO(0) == in_it) {
					dc->SetTextForeground(*wxBLACK);
				}else{
					dc->SetTextForeground(*wxRED);
				}
				dc->DrawText(IntToStr(dbweekly.Item(i).GetAmount(0)),textpos.x+vpos.x,y);
				textpos.x += colwidth[2]*mm_to_logi;
			}
		}
		cnt++;
		y += tmpy + linespace;
	}

}
void ReportPrintout::DrawSearchReport(wxDC *dc, int page, float mm_to_logi, int pw, int ph)
{
	int x, y;
    int pageWidthMM, pageHeightMM;
	int realw, realh;
	int tmpx, tmpy;
	wxPoint textpos;
	wxString colname[] = {
		_("Date"),_("Expense and Item"),_("Account"),_("Memo"),_("Amount")
	};
	int colwidth[] = {
		20,50,30,50,15
	};
    GetPageSizeMM(&pageWidthMM, &pageHeightMM);
	pageWidthMM *= mm_to_logi;
	pageHeightMM *= mm_to_logi;
	//---set initial position and page size
	x = (int)(mm_to_logi * (float)margin_tl.x);
	y = (int)(mm_to_logi * (float)margin_tl.y);
	realw = (pw - x);
	realh = (ph - y);
	//y += 64;

	dc->SetFont(textfont);
	dc->SetTextForeground(*wxBLACK);
	dc->SetPen(*wxBLACK_PEN);

	//---draw condition to search
	{
		textfont.SetPointSize(14);
		dc->SetFont(textfont);
		dc->GetTextExtent(_("Condition to search"),&tmpx,&tmpy);
		textpos = GetLeftingDrawing(y,x,30);
		dc->DrawText(_("Condition to search"),textpos.x,y);
		y += tmpy;
		dc->DrawLine(textpos.x-5,y, textpos.x+tmpx+5,y);
		y += linespace;
		
		textfont.SetPointSize(12);
		dc->SetFont(textfont);
		for (size_t i = 0; i < searchconditions.GetCount(); i++) {
			dc->GetTextExtent(searchconditions.Item(i),&tmpx,&tmpy);
			textpos = GetLeftingDrawing(y,x,30);
			dc->SetBrush(*wxBLACK_BRUSH);
			dc->DrawCircle(textpos.x+3,y+8,4);
			dc->SetBrush(*wxWHITE_BRUSH);
			textpos = GetLeftingDrawing(y,x,50);
			dc->DrawText(searchconditions.Item(i),textpos.x,y);
			y += tmpy + linespace;
		}
	}
	//------draw other data
	textfont.SetPointSize(10);
	dc->SetFont(textfont);
	{
		y += linespace + 10;
		//------draw column name
		textpos.x = x + 5;
		for (int i = 0; i < WXSIZEOF(colname); i++) {
			dc->GetTextExtent(colname[i],&tmpx,&tmpy);
			dc->DrawText(colname[i],textpos.x, y);
			textpos.x += colwidth[i]*mm_to_logi;
		}
		y += tmpy + linespace;
	}
	//------draw each data
	int cnt = 0;
	if (page < oldpage) {
		//------if return previous page, return index too.
		startdataindex = data_perpage * (page - 1);
	}
	for (int i = startdataindex; i < (int)dbdata.size(); i++) {
		textpos.x = x + 5;
		dc->SetTextForeground(*wxBLACK);
		if (cnt >= data_perpage) {
			break;
		}else{
			wxArrayString arr;
			DB_day db = dbdata.at(i);
			arr = wxGetApp().AppDB.GetStringDayTransaction(dbdata.at(i));
			//combine expenditure to income
			if (db.GetExpenditure() > 0) {
				arr.Item(4) = _T("-");
				arr.Item(4).Append(arr.Item(5));
			}
			//combine item to expense
			arr.Item(1).Append(_T("("));
			arr.Item(1).Append(arr.Item(2));
			arr.Item(1).Append(_T(")"));
			wxString memo = arr.Item(6);
			//---delete and sort
			arr.RemoveAt(6); //Memo
			arr.RemoveAt(5); //Expenditure
			arr.RemoveAt(2); //Item
			//arr.RemoveAt(3); //Account
			//arr.RemoveAt(0); //Date
			arr.Insert(memo,3);
			for (int j = 0; j < (int)arr.GetCount(); j++) {
				dc->GetTextExtent(arr.Item(j),&tmpx,&tmpy);
				if (j <= 3) {
					dc->DrawText(arr.Item(j),textpos.x,y);
				}else{
					//------numeric columns 
					wxPoint vpos;
					if (arr.Item(j).Find(_T("-")) > wxNOT_FOUND) dc->SetTextForeground(*wxRED);
					vpos = GetRightingDrawing(colwidth[j]*mm_to_logi,y,tmpx,tmpy);
					dc->DrawText(arr.Item(j),textpos.x+vpos.x,y);
				}
				textpos.x += colwidth[j]*mm_to_logi;
			}

		}
		cnt++;
		y += tmpy + linespace;
	}

}
